package com.lin.generate.common.utill;

import cn.hutool.core.codec.Base64;
import com.google.common.collect.Maps;
import com.lin.generate.common.enums.SystemEnums;
import com.lin.generate.common.exception.BusinessException;
import io.jsonwebtoken.*;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

/**
 * @Author wei cao
 * @Date 2020/9/1 10:22
 * @Version 1.0
 */
public class JwtHelper {

    /**
     * 创建JWT密匙
     */
    private static final String JWT_SECRET = "GNIOADGM43413RMLKADFI4SFNK43MKL14353M3KL5J353=";

    public static String createJWT(Map<String, Object> claims, Long ttlMillis) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SecretKey secretKey = generalKey();
        JwtBuilder builder = Jwts.builder()
                .setClaims(claims)
                //签发者
                .setIssuer("system")
                //签发时间
                .setIssuedAt(now)
                //签名算法以及密匙
                .signWith(secretKey, signatureAlgorithm);
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date expDate = new Date(expMillis);
            //过期时间
            builder.setExpiration(expDate);
        }
        return "xy_idc " + builder.compact();
    }

    /**
     * 获取tooken中的参数值
     *
     * @param token 要解析的token信息
     * @return
     * @throws Exception
     */
    public static Map<String, Object> extractInfo(String token) throws BusinessException {
        token = token.replaceAll("xy_idc ", "");
        Optional<Claims> claims = getClaimsFromToken(token);
        if (claims.isPresent()) {
            Map<String, Object> info = Maps.newHashMap();
            Set<String> keySet = claims.get().keySet();
            //通过迭代，提取token中的参数信息
            for (String key : keySet) {
                Object value = claims.get().get(key);
                info.put(key, value);
            }
            return info;
        }
        return null;
    }

    public static Optional<Claims> getClaimsFromToken(String token) throws BusinessException {
        Claims claims;
        SecretKey secretKey = generalKey();
        try {
            claims = Jwts.parser()
                    .setSigningKey(secretKey)
                    .parseClaimsJws(token)
                    .getBody();
            return Optional.of(claims);
        } catch (ExpiredJwtException e) {
            throw new BusinessException(SystemEnums.LOGIN_INVALID.getMsg());
        } catch (Exception e) {
            throw new BusinessException((SystemEnums.TOKEN_VALID).getMsg());
        }
    }

    private static SecretKey generalKey() {
        byte[] encodedKey = Base64.decode(JWT_SECRET);
        return new SecretKeySpec(encodedKey, 0, encodedKey.length, "HmacSHA256");
    }
}
